import fg from 'fast-glob'
import fs from 'fs-extra'
import path from 'path';
import { Ancestor } from './Ancestor.js';

interface IPackageSet {
    name: string;
    tails: string[];
}

export class Cleaner extends Ancestor {

    public async awake(): Promise<boolean> {
        return true;
    }

    public async start(): Promise<void> {
        const roots = this.cmdOption.taskParameter!.split(',');
        for (const root of roots) {
            console.log('handling directory:', root);
            await this.deletePackages(root);
            await this.cleanWebGL(root);
        }
    }
    
    public async deletePackages(dir: string): Promise<void> {
        const files = await fs.readdir(dir);

        const pkgMap: { [name: string]: IPackageSet } = {};
        for (const f of files) {
            const file = path.join(dir, f);
            const fstat = await fs.stat(file);
            if (fstat.isDirectory()) {
                await this.deletePackages(file);
            } else {
                if (f.startsWith('.')) {
                    await fs.unlink(file);
                    continue;
                }
                let tailLen = -1;
                const zipMch = f.match(/^.+\.pc\.\d{5}\.zip$/);
                if (zipMch != null) {
                    // fengyue_dldlweb_korea_test.pc.02885.zip
                    tailLen = 9;
                } else {
                    const pkgMch = f.match(/^.+?\.v([.\d]+)\.apk$/);
                    if (pkgMch != null) {
                        // com.jzdl.bt.dev.v1.0.31.2865.apk
                        tailLen = pkgMch[1].length + 4;
                    }
                }
                if (tailLen > 0) {                    
                    const name = file.substring(0, file.length - tailLen);
                    const tail = file.substring(file.length - tailLen);
                    let pset = pkgMap[name];
                    if (pset == null) {
                        pkgMap[name] = pset = { name, tails: [tail] };
                    } else {
                        if (!pset.tails.includes(tail))
                            pset.tails.push(tail);
                    }
                }
            }
        }

        for (const name in pkgMap) {
            const pset = pkgMap[name];
            console.log(name, pset.tails.join(','));
            if (pset.tails.length > 2) {
                pset.tails.sort();
                for (let i = pset.tails.length - 2; i >= 0; i--) {
                    const file = pset.name + pset.tails[i];
                    console.log('deleting', file);
                    if (!this.cmdOption.debug) {
                        if (fs.existsSync(file)) await fs.unlink(file);
                        // delete .png
                        const ext = path.extname(file);
                        // delete .aab
                        const aab = file.replace(ext, '.aab');
                        if (fs.existsSync(aab)) await fs.unlink(aab);
                        const png = file.replace(ext, '.png');
                        if (fs.existsSync(png)) await fs.unlink(png);
                    }
                }
            }
        }
    }

    public async cleanWebGL(dir: string): Promise<void> {
        const browserDirs = await fg('*/browser', { cwd: dir, onlyDirectories: true });
        console.log('browser directories:', browserDirs);
        for (const bd of browserDirs) {
            const root = path.join(dir, bd);
            const index = path.join(root, 'index.html');
            const indexContent = await fs.readFile(index, 'utf-8');
            const puertsRuntimeJs = indexContent.match(/puerts-runtime_\w{6}\.js/);
            const puertsBrowserJsResourcesJs = indexContent.match(/puerts_browser_js_resources_\w{6}\.js/);
            const jsFiles = await fg('*.js', { cwd: root });
            for (const jsf of jsFiles) {
                if (jsf != puertsRuntimeJs?.[0] && jsf != puertsBrowserJsResourcesJs?.[0]) {
                    await fs.unlink(path.join(root, jsf));
                }
            }

            const buildRoot = path.join(root, 'Build');
            const loaderURL = indexContent.match(/export_browser_\w{6}\.loader\.js/);
            const dataURL = indexContent.match(/export_browser_\w{6}\.data\.gz/);
            const frameworkURL = indexContent.match(/export_browser_\w{6}\.framework\.js\.gz/);
            const codeURL = indexContent.match(/export_browser_\w{6}\.wasm\.gz/);
            const buildFiles = await fg(['*.js', '*.gz'], { cwd: buildRoot });
            for (const bf of buildFiles) {
                if (bf != loaderURL?.[0] && bf != dataURL?.[0] && bf != frameworkURL?.[0] && bf != codeURL?.[0]) {
                    await fs.unlink(path.join(buildRoot, bf));
                }
            }
        }
    }
}